﻿using System;using System.Collections.Generic;
using System.Text;
using MigratorCore.Actions;
using MigratorCore.Bases;
using MigratorCore.Objects;
using MigratorCore.Status;
using MigratorCore;
using System.Data.SqlClient;
using System.Data;

namespace Migrator.CommunityServer.version2007_1
{
    public class ForumsDestination : IDestinationAction
    {
        #region IDestinationAction Members
        System.Collections.Generic.Dictionary<string, int> users;
        int xn = 0;
        public void Set()
        {
            if (this.Objects != null && this.Objects.Count > 0) {
                status.AddEvent(new Event(EventType.Information, "Initizing", "Initizing Database Connection", DateTime.Now));
                SqlConnection con = new SqlConnection(this.settings["ConnectionString"].ToString());
                SqlCommand cmd = new SqlCommand("SELECT UserID, Email FROM cs_Users", con);
                SqlDataReader read;
                try
                {
                    con.Open();
                    read = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                }
                catch (Exception e)
                {
                    status.Completed = 100;
                    status.AddEvent(new Event(EventType.CriticalError, "Database Connection Failed", "The Connection to the Database Failed", e, DateTime.Now));
                    return;
                }
                status.AddEvent(new Event(EventType.Information, "Loading Users", "Loading user ID's and Usernames from Database", DateTime.Now));
                users = new Dictionary<string, int>();
                while (read.Read()) users.Add(read.GetString(1), read.GetInt32(0));
                read.Dispose();
                cmd.Dispose();
                StringBuilder sb = new StringBuilder();
                #region Get Setting ID
                cmd = new SqlCommand("SELECT [SettingsID] FROM [dbo].[cs_SiteSettings] WHERE [ApplicationName] = '" + settings["Application Name"].ToString() + "'", con);
                con.Open();
                int sitesettingid = Convert.ToInt32(cmd.ExecuteScalar());
                cmd.Dispose();
                con.Close();
                #endregion
                xn = 0;
                int x = 0;
                status.AddEvent(new Event(EventType.Information, "Processing Groups", "Starting to Import Groups", DateTime.Now));
                foreach (Forum forum in this.Objects)
                {
                    x++;
                    status.AddEvent(new Event(EventType.Information, "Processing " + forum.Name, "Processing group " + forum.Name, DateTime.Now));
                    //Build Groups from top level forums
                    cmd = new SqlCommand("[dbo].[cs_Group_CreateUpdateDelete]", con);
                    cmd.CommandType = CommandType.StoredProcedure;
                    SqlParameter groupid = new SqlParameter("@GroupID", SqlDbType.Int);
                    groupid.Direction = ParameterDirection.Output;
                    cmd.Parameters.Add(groupid);
                    cmd.Parameters.AddWithValue("@Name", forum.Name);
                    cmd.Parameters.AddWithValue("@Description", forum.Description);
                    cmd.Parameters.AddWithValue("@ApplicationType", 0);
                    cmd.Parameters.AddWithValue("@Action", 0);
                    cmd.Parameters.AddWithValue("@SettingsID", sitesettingid);
                    con.Open();
                    try
                    {
                        cmd.ExecuteNonQuery();
                    }
                    catch (Exception e) { status.AddEvent(new Event(EventType.MissingData, "Something went wrong", "Something went wrong adding the forum group", e, DateTime.Now)); }
                    con.Close();
                    status.AddEvent(new Event(EventType.Information, "Processing Forums in Group " + forum.Name, "Processing Forums in Group " + forum.Name, DateTime.Now));
                    xn = 0;
                    parseforums(forum, Convert.ToInt32(cmd.Parameters["@GroupID"].Value), 0, sitesettingid);
                    status.Completed = Convert.ToInt32(Math.Round((double)((this.Objects.Count) / x) * 100, 0));
                }
                status.Completed = 100;
            }
        }

        private void parseforums(Forum f, int groupid, int parent, int settingsid)
        {
            foreach (Forum forum in f.Forums)
            {
                xn++;
                status.AddEvent(new Event(EventType.Information, "Processing Forum " + forum.Name, "Processing Forum " + forum.Name + " in group " + f.Name, DateTime.Now));
                SqlConnection con = new SqlConnection(this.settings["ConnectionString"].ToString());
                SqlCommand cmd = new SqlCommand("[dbo].[cs_Section_CreateUpdateDelete]", con);
                cmd.CommandType = CommandType.StoredProcedure;
                SqlParameter sectionid = new SqlParameter("@SectionID", SqlDbType.Int);
                sectionid.Direction = ParameterDirection.Output;
                cmd.Parameters.Add(sectionid);
                cmd.Parameters.AddWithValue("@DeleteForum", 0);
                cmd.Parameters.AddWithValue("@Name", forum.Name);
                cmd.Parameters.AddWithValue("@Url", "");
                cmd.Parameters.AddWithValue("@Description", forum.Description);
                cmd.Parameters.AddWithValue("@ParentID", parent);
                cmd.Parameters.AddWithValue("@SettingsID", settingsid);
                cmd.Parameters.AddWithValue("@GroupID", groupid);
                cmd.Parameters.AddWithValue("@IsModerated", 1);
                cmd.Parameters.AddWithValue("@IsSearchable", 1);
                cmd.Parameters.AddWithValue("@DisplayPostsOlderThan", 0);
                cmd.Parameters.AddWithValue("@IsActive", 1);
                cmd.Parameters.AddWithValue("@EnablePostStatistics", 1);
                cmd.Parameters.AddWithValue("@EnablePostPoints", 1);
                cmd.Parameters.AddWithValue("@EnableAutoDelete", 0);
                cmd.Parameters.AddWithValue("@EnableAnonymousPosting", 0);
                cmd.Parameters.AddWithValue("@AutoDeleteThreshold", 0);
                cmd.Parameters.AddWithValue("@SortOrder", 0);
                cmd.Parameters.AddWithValue("@PropertyNames", null);
                cmd.Parameters.AddWithValue("@PropertyValues", null);
                cmd.Parameters.AddWithValue("@ApplicationKey", "forum-" + forum.Name.Replace(' ', '-').Trim());
                cmd.Parameters.AddWithValue("@ApplicationType", 0);
                cmd.Parameters.AddWithValue("@ForumType", 0);
                cmd.Parameters.AddWithValue("@UserID", 2100);
                cmd.Parameters.AddWithValue("@DefaultLanguage", "en-us");
                con.Open();
                //try
                //{
                    cmd.ExecuteNonQuery();
                    if (forum.Posts.Count > 0) parseforumposts(forum.Posts, Convert.ToInt32(cmd.Parameters["@SectionID"].Value), 0, settingsid);
                    if (forum.Forums.Count > 0) parseforums(forum, groupid, Convert.ToInt32(cmd.Parameters["@SectionID"].Value), settingsid);
                    status.AddEvent(new Event(EventType.Information, "Processed Forum " + forum.Name, "Processed forum " + forum.Name, DateTime.Now));
                //}
                //catch (Exception e) { status.AddEvent(new Event(EventType.MissingData, "Error Processing Forum " + forum.Name, e.Message, e, DateTime.Now)); }
            }
        }

        private void parseforumposts(List<Post> posts, int sectionid, int parent, int settingsid)
        {
            foreach (Post post in posts)
            {
                SqlConnection con = new SqlConnection(this.settings["ConnectionString"].ToString());
                SqlCommand cmd = new SqlCommand("[dbo].[cs_Post_CreateUpdate]", con);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@SectionID", sectionid);
                cmd.Parameters.AddWithValue("@ParentID", parent);
                cmd.Parameters.AddWithValue("@AllowDuplicatePosts", 0);
                cmd.Parameters.AddWithValue("@DuplicateIntervalInMinutes", parent);
                cmd.Parameters.AddWithValue("@Subject", post.Subject);
                cmd.Parameters.AddWithValue("@UserID", users[post.User.Email]);
                cmd.Parameters.AddWithValue("@PostAuthor", post.User.Name);
                cmd.Parameters.AddWithValue("@Body", post.Body);
                cmd.Parameters.AddWithValue("@FormattedBody", post.Body);
                cmd.Parameters.AddWithValue("@EmoticonID", 0);
                cmd.Parameters.AddWithValue("@IsLocked", 0);
                cmd.Parameters.AddWithValue("@IsSticky", 0);
                cmd.Parameters.AddWithValue("@StickyDate", post.Posted);
                cmd.Parameters.AddWithValue("@PostType", 0);
                cmd.Parameters.AddWithValue("@PostMedia", 0);
                cmd.Parameters.AddWithValue("@PostDate", post.Posted);
                cmd.Parameters.AddWithValue("@UserHostAddress", "0.0.0.0");
                cmd.Parameters.AddWithValue("@PropertyNames", null);
                cmd.Parameters.AddWithValue("@PropertyValues", null);
                cmd.Parameters.AddWithValue("@SettingsID", settingsid);
                cmd.Parameters.AddWithValue("@IsTracked", 0);
                SqlParameter postid = new SqlParameter("@PostID", SqlDbType.Int);
                postid.Direction = ParameterDirection.Output;
                cmd.Parameters.Add(postid);
                SqlParameter threadid = new SqlParameter("@ThreadID", SqlDbType.Int);
                threadid.Direction = ParameterDirection.Output;
                cmd.Parameters.Add(threadid);
                cmd.Parameters.AddWithValue("@UpdateSectionStatistics", 1);
                cmd.Parameters.AddWithValue("@UserTime", post.Posted);
                cmd.Parameters.AddWithValue("@ApplicationPostType", 0);
                cmd.Parameters.AddWithValue("@PostName", null);
                cmd.Parameters.AddWithValue("@ThreadStatus", 0);
                cmd.Parameters.AddWithValue("@Points", 0);
                cmd.Parameters.AddWithValue("@PostDisplayName", post.User.Name);
                cmd.Parameters.AddWithValue("@AutoApprove", 1);
                cmd.Parameters.AddWithValue("@IsApproved", 1);
                con.Open();
                try
                {
                    xn++;
                    status.AddEvent(new Event(EventType.Information, "Processing Post " + xn.ToString(), "Fully Processing Post " + xn.ToString(), DateTime.Now));
                    cmd.ExecuteNonQuery();
                    if (!cmd.Parameters["@PostID"].Value.GetType().Equals(typeof(DBNull)))
                        if (post.Posts.Count > 0)
                            parseforumposts(post.Posts, sectionid, Convert.ToInt32(cmd.Parameters["@PostID"].Value), settingsid);
                }
                catch (Exception e) { status.AddEvent(new Event(EventType.MissingData, "Error Processing Post " + xn.ToString(), "Error Processing Post " + xn.ToString(), e, DateTime.Now)); }
                finally
                {
                    con.Close();
                }
            }
        }

        #endregion

        #region IAction Members

        private Settings settings;
        public Settings Settings
        {
            get
            {
                if (settings == null)
                {
                    settings = new Settings();
                    settings.Add("ConnectionString", "server=(localhost);uid=;pwd=;Trusted_Connection=yes;database=CommunityServer");
                    settings.Add("Application Name", "dev");
                }
                return settings;
            }
        }

        public string Name
        {
            get { return "Forums Destination"; }
        }

        private Status status;
        public Status Status
        {
            get
            {
                if (status == null)
                    status = new Status();
                return status;
            }
        }

        private ObjectSet objects;
        public ObjectSet Objects
        {
            get
            {
                if (objects == null) objects = new ObjectSet();
                return objects;
            }
            set
            {
                objects = value;
            }
        }

        public ActionType ActionType
        {
            get
            {
                return ActionType.Forums;
            }
        }


        #endregion
    }
}
